package com.dongbo.recorder.screenrecord.utils;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;

import com.dongbo.recorder.screenrecord.bean.ScreenRecordBean;
import com.dongbo.recorder.screenrecord.bean.ScreenShotBean;
import com.dongbo.recorder.screenrecord.AppLpds;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import okio.BufferedSource;
import okio.Okio;
import okio.Sink;

/**
 * @Description:
 * @Author: gstory0404@gmail
 * @CreateDate: 2020/4/30 15:41
 */
public class FileUtils {
    /**
     * 保存录屏文件目录
     *
     * @return
     */
    public static String getScreenRecordFile() {
        String rootDir = AppLpds.getInstance().getFilesDir().getAbsolutePath() + "/" + "ZkhcScreenRecord" + "/";
        File file = new File(rootDir);
        if (!file.exists()) {
            if (!file.mkdirs()) {
                return null;
            }
        }
        return rootDir;
    }

    public static String getScreenRecord0File() {
        String rootDir = AppLpds.getInstance().getExternalFilesDir("").getAbsolutePath() + "/" + "ZkhcScreenRecord" + "/";
        File file = new File(rootDir);
        if (!file.exists()) {
            if (!file.mkdirs()) {
                return null;
            }
        }
        return rootDir;
    }

    public static String getRecordFileD(String mName) {
        String mPath = getScreenRecordFile() + "0x";
        File file = new File(mName);
        if (!file.exists()) {
            return mPath;
        } else if (getFileName(mName).startsWith("1x")) {
            mPath = getScreenRecordFile() + "1x";
        }
        return mPath;
    }

    /**
     * 返回保存的文件名（包含是否有音频）
     *
     * @return
     */
    public static String getRecordFileName(ArrayList<String> mList) {
        String mPath = getScreenRecordFile() + "0x" + System.currentTimeMillis() + ".mp4";
        for (String mP : mList) {
            if (getFileName(mP).startsWith("1x")) {
                mPath = getScreenRecordFile() + "1x" + System.currentTimeMillis() + ".mp4";
                break;
            }
        }
        return mPath;
    }

    /**
     * 返回保存的文件名（包含是否有音频）
     *
     * @return
     */
    public static String getRecordFileName(String mName) {
        String mPath = getScreenRecordFile() + "0x" + System.currentTimeMillis() + ".mp4";
        File file = new File(mName);
        if (!file.exists()) {
            return mPath;
        } else if (getFileName(mName).startsWith("1x")) {
            mPath = getScreenRecordFile() + "1x" + System.currentTimeMillis() + ".mp4";
        }
        return mPath;
    }

    /**
     * 保存截图文件目录
     *
     * @return
     */
    public static String getScreenshotFile() {
        String rootDir = AppLpds.getInstance().getFilesDir().getAbsolutePath() + "/" + "Screenshot" + "/";
        File file = new File(rootDir);
        if (!file.exists()) {
            if (!file.mkdirs()) {
                return null;
            }
        }
        return rootDir;
    }

    /**
     * 保存缓存文件目录
     *
     * @return
     */
    public static String getCacheFile() {
        String rootDir = AppLpds.getInstance().getFilesDir().getAbsolutePath() + "/" + "MyCache" + "/";
        File file = new File(rootDir);
        if (!file.exists()) {
            if (!file.mkdirs()) {
                return null;
            }
        }
        return rootDir;
    }

    /**
     * 创建根目录
     *
     * @return
     */
    public static String getRootFile() {
        String rootDir = Environment.getExternalStorageDirectory() + "/" + "lpds" + "/";
        File file = new File(rootDir);
        if (!file.exists()) {
            if (!file.mkdirs()) {
                return null;
            }
        }
        return rootDir;
    }

    /**
     * 移动文件
     *
     * @param context 上下文
     * @param oldPath 旧路径
     * @param newPath 新路径
     * @return
     */
    public static boolean getMoveFile(Context context, String oldPath, String newPath, boolean isOut) {
        if (FileUtils.copyFile(context, oldPath, newPath, isOut)) {
            //发送通知 相册显示
            Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
            Uri uri = Uri.fromFile(new File(newPath));
            intent.setData(uri);
            context.sendBroadcast(intent);
            return true;
        }
        return false;
    }


    /**
     * 获取所有录屏文件
     *
     * @return
     */
    public static List<ScreenRecordBean> getAllScreenRecordFile() {
        File file = new File(getScreenRecordFile());
        File[] files = file.listFiles();
        if (files == null) {
            Log.e("error", "空目录");
            return null;
        }
        List<ScreenRecordBean> s = new ArrayList<>();
        for (int i = 0; i < files.length; i++) {
            File f = new File(getScreenRecordFile() + files[i].getName());
            //过滤非MP4文件
            if (getFormatName(f.getName()).equals("mp4")) {
                ScreenRecordBean screenRecordBean = new ScreenRecordBean();
                //名称
                screenRecordBean.setFlieName(f.getName());
                //路径
                screenRecordBean.setPath(f.getAbsolutePath());
                //大小
                screenRecordBean.setSize(FileSizeUtil.getAutoFileOrFilesSize(f.getAbsolutePath()));
                //时长
                screenRecordBean.setDate(getLocalVideoDuration(f.getAbsolutePath()));
                screenRecordBean.setCreatTime(f.lastModified());
                s.add(screenRecordBean);
            }
        }
        Collections.sort(s, new Comparator<ScreenRecordBean>() {
            /*
             * int compare(Student o1, Student o2) 返回一个基本类型的整型，
             * 返回负数表示：o1 小于o2，
             * 返回0 表示：o1和o2相等，
             * 返回正数表示：o1大于o2。
             */
            public int compare(ScreenRecordBean o1, ScreenRecordBean o2) {
                //根据时间 倒叙
                if (o1.getCreatTime() < o2.getCreatTime()) {
                    return 1;
                }
                if (o1.getCreatTime() == o2.getCreatTime()) {
                    return 0;
                }
                return -1;
            }
        });
        return s;
    }

    /**
     * 获取所有截屏文件
     *
     * @return
     */
    public static List<ScreenShotBean> getAllScreenshotFile() {
        File file = new File(getScreenshotFile());
        File[] files = file.listFiles();
        if (files == null) {
            Log.e("error", "空目录");
            return null;
        }
        List<ScreenShotBean> s = new ArrayList<>();
        for (int i = 0; i < files.length; i++) {
            File f = new File(getScreenshotFile() + files[i].getName());
            //过滤非jpg png文件
            String name = getFormatName(f.getName());
            if (name.equals("jpg") || name.equals("png")) {
                ScreenShotBean screenShotBean = new ScreenShotBean();
                //名称
                screenShotBean.setFlieName(f.getName());
                //路径
                screenShotBean.setPath(f.getAbsolutePath());
                //大小
                screenShotBean.setSize(FileSizeUtil.getAutoFileOrFilesSize(f.getAbsolutePath()));
                //时长
                screenShotBean.setCreatTime(f.lastModified());
                s.add(screenShotBean);
                Log.d("gstory", screenShotBean.toString());
            }
        }
        Collections.sort(s, new Comparator<ScreenShotBean>() {
            /*
             * int compare(Student o1, Student o2) 返回一个基本类型的整型，
             * 返回负数表示：o1 小于o2，
             * 返回0 表示：o1和o2相等，
             * 返回正数表示：o1大于o2。
             */
            public int compare(ScreenShotBean o1, ScreenShotBean o2) {
                //根据时间 倒叙
                if (o1.getCreatTime() < o2.getCreatTime()) {
                    return 1;
                }
                if (o1.getCreatTime() == o2.getCreatTime()) {
                    return 0;
                }
                return -1;
            }
        });
        return s;
    }

    /**
     * get Local video duration
     *
     * @return
     */
    public static int getLocalVideoDuration(String videoPath) {
        int duration;
        try {
            MediaMetadataRetriever mmr = new MediaMetadataRetriever();
            mmr.setDataSource(videoPath);
            duration = Integer.parseInt(mmr.extractMetadata
                    (MediaMetadataRetriever.METADATA_KEY_DURATION));
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
        return duration;
    }

    /**
     * 获取文件格式名
     */
    public static String getFormatName(String filename) {
        if ((filename != null) && (filename.length() > 0)) {
            int dot = filename.lastIndexOf('.');
            if ((dot > -1) && (dot < (filename.length() - 1))) {
                return filename.substring(dot + 1);
            }
        }
        return filename;
    }

    /**
     * 重命名文件
     *
     * @param oldPath 原来的文件地址
     * @param newPath 新的文件地址
     */
    public static void renameFile(String oldPath, String newPath) {
        File oleFile = new File(oldPath);
        File newFile = new File(newPath);
        //执行重命名
        oleFile.renameTo(newFile);
    }


    /**
     * 创建写入内容文件
     * 请注意一定要申请文件读写权限
     *
     * @return
     */
    public static String createInputFile(Context context, String... filePaths) {
        File file = new File(getScreenRecordFile(), "input.txt");
        String content = "";
        for (String filePath : filePaths) {
            content += "file " + getFileName(filePath) + "\n";
        }
        if (!file.exists()) {
            try {
                file.createNewFile();
                RandomAccessFile raf = new RandomAccessFile(file, "rwd");
                raf.seek(file.length());
                raf.write(content.getBytes());
                raf.close();
                return file.getAbsolutePath();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        } else {
            file.delete();
            return createInputFile(context, filePaths);
        }
    }


    public static String getFileName(String filePath) {
        return filePath.substring(filePath.lastIndexOf(File.separator) + 1);
    }

    /**
     * 复制单个文件
     *
     * @param oldPath$Name 原文件路径+文件名
     * @param newPath$Name 复制后路径+文件名
     * @return
     */
    public static boolean copyFile(Context context, String oldPath$Name, String newPath$Name, boolean isOut) {
        if (isOut && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            File oldFile = new File(oldPath$Name);
            if (!oldFile.exists() || !oldFile.isFile() || !oldFile.canRead()) {
                return false;
            }
            return insertVideo(context, oldPath$Name);
        } else {
            try {
                File oldFile = new File(oldPath$Name);
                if (!oldFile.exists() || !oldFile.isFile() || !oldFile.canRead()) {
                    return false;
                }
                FileInputStream fileInputStream = new FileInputStream(oldPath$Name);    //读入原文件
                FileOutputStream fileOutputStream = new FileOutputStream(newPath$Name);
                byte[] buffer = new byte[1024];
                int byteRead;
                while ((byteRead = fileInputStream.read(buffer)) != -1) {
                    fileOutputStream.write(buffer, 0, byteRead);
                }
                fileInputStream.close();
                fileOutputStream.flush();
                fileOutputStream.close();
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    }

//    /**
//     * 保存视频
//     *
//     * @param file
//     */
//    public static boolean saveVideo(Context context, File file) {
//        //是否添加到相册
//        ContentResolver localContentResolver = context.getContentResolver();
//        ContentValues localContentValues = getVideoContentValues(file, System.currentTimeMillis());
////        Uri localUri = localContentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, localContentValues);
//        Uri videoTable = Uri.parse(VIDEO_BASE_URI);
//        Uri localUri = localContentResolver.insert(videoTable, localContentValues);
//        context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, localUri));
//        return true;
//    }
//
//    public static ContentValues getVideoContentValues(File paramFile, long paramLong) {
//        ContentValues localContentValues = new ContentValues();
////        localContentValues.put(MediaStore.Images.Media.TITLE, paramFile.getName());//标题
//        localContentValues.put(MediaStore.Images.Media.DISPLAY_NAME, paramFile.getName());//文件名
////        localContentValues.put(MediaStore.Images.Media.BUCKET_DISPLAY_NAME, "luping");// 直接包含该文件的文件夹名
//        localContentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, "Movies/" + "luping");
//        localContentValues.put(MediaStore.Video.Media.IS_PENDING, 1);
//        localContentValues.put(MediaStore.Images.Media.MIME_TYPE, "video/mp4");//数据类型MP4
//        localContentValues.put(MediaStore.Images.Media.DATE_TAKEN, Long.valueOf(paramLong));//拍摄日期
//        localContentValues.put(MediaStore.Images.Media.DATE_MODIFIED, Long.valueOf(paramLong));//修改日期
//        localContentValues.put(MediaStore.Images.Media.DATE_ADDED, Long.valueOf(paramLong));//保存日期
//        localContentValues.put(MediaStore.Images.Media.DATA, paramFile.getAbsolutePath());//数据绝对路径
//        localContentValues.put(MediaStore.Images.Media.SIZE, Long.valueOf(paramFile.length()));//大小
//        return localContentValues;
//    }

    private static final String VIDEO_BASE_URI = "content://media/external/video/media";

    private static boolean insertVideo(Context context, String videoPath) {
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        retriever.setDataSource(videoPath);

        int nVideoWidth = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
        int nVideoHeight = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
        int duration = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));

        long dateTaken = System.currentTimeMillis();
        File file = new File(videoPath);
        String title = file.getName();
        String filename = file.getName();
        String mime = "video/mp4";
        ContentValues mCurrentVideoValues = new ContentValues(9);
        mCurrentVideoValues.put(MediaStore.Video.Media.TITLE, title);
        mCurrentVideoValues.put(MediaStore.Video.Media.DISPLAY_NAME, filename);
        mCurrentVideoValues.put(MediaStore.Video.Media.DATE_TAKEN, dateTaken);
        mCurrentVideoValues.put(MediaStore.MediaColumns.DATE_MODIFIED, dateTaken / 1000);
        mCurrentVideoValues.put(MediaStore.Video.Media.MIME_TYPE, mime);
        mCurrentVideoValues.put(MediaStore.Video.Media.DATA, videoPath);
        mCurrentVideoValues.put(MediaStore.Video.Media.WIDTH, nVideoWidth);
        mCurrentVideoValues.put(MediaStore.Video.Media.HEIGHT, nVideoHeight);
        mCurrentVideoValues.put(MediaStore.Video.Media.RESOLUTION, Integer.toString(nVideoWidth) + "x" + Integer.toString(nVideoHeight));
        mCurrentVideoValues.put(MediaStore.Video.Media.SIZE, new File(videoPath).length());
        mCurrentVideoValues.put(MediaStore.Video.Media.DURATION, duration);
        mCurrentVideoValues.put(MediaStore.MediaColumns.RELATIVE_PATH, "Movies/" + "lpds");

        ContentResolver contentResolver = context.getContentResolver();
        Uri videoTable = Uri.parse(VIDEO_BASE_URI);
        Uri uri = contentResolver.insert(videoTable, mCurrentVideoValues);
        return writeFile(videoPath, mCurrentVideoValues, contentResolver, uri);
    }

    private static boolean writeFile(String imagePath, ContentValues values, ContentResolver contentResolver, Uri item) {
        try (OutputStream rw = contentResolver.openOutputStream(item, "rw")) {
            // Write data into the pending image.
            Sink sink = Okio.sink(rw);
            BufferedSource buffer = Okio.buffer(Okio.source(new File(imagePath)));
            buffer.readAll(sink);
            values.put(MediaStore.Video.Media.IS_PENDING, 0);
            contentResolver.update(item, values, null, null);
//            new File(imagePath).delete();

            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                Cursor query = AppLpds.getInstance().getApplicationContext().getContentResolver().query(item, null, null, null);
                if (query != null) {
                    int count = query.getCount();
                    Log.e("writeFile", "writeFile result :" + count);
                    query.close();
                }
            }
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

//    public static boolean insertVideo(Context context, String filePath) {
//        if (TextUtils.isEmpty(filePath)) {
//            return false;
//        } else {
//            int d = 0;
//            int w = 0;
//            int h = 0;
//            try {
//                MediaMetadataRetriever mmr = new MediaMetadataRetriever();
//                mmr.setDataSource(filePath);
//                w = Integer.parseInt(mmr.extractMetadata(18));
//                h = Integer.parseInt(mmr.extractMetadata(19));
//                d = Integer.parseInt(mmr.extractMetadata(9));
//                mmr.release();
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//            File file = new File(filePath);
//            ContentValues cv = getCv(file, w, h, true, name);
//            cv.put("duration", d);
//            if (Build.VERSION.SDK_INT >= 29 && file.getAbsolutePath().startsWith(context.getExternalFilesDir((String) null).getParent())) {
//                return getUri(context, file, cv, true, FileUtils.getRootFile());
//            } else {
//                cv.put("_data", file.getAbsolutePath());
//                Uri uri = context.getContentResolver().insert(android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI, cv);
//                if (uri != null) {
//                    context.sendBroadcast(new Intent("android.intent.action.MEDIA_SCANNER_SCAN_FILE", uri));
//                }
//
//                return true;
//            }
//        }
//    }

    private static ContentValues getCv(File file, int w, int h, boolean isVideo, String name) {
        ContentValues cv = new ContentValues();
        cv.put("title", name);
        cv.put("mime_type", isVideo ? "video/mp4" : "image/jpeg");
        cv.put("artist", name);
        cv.put("datetaken", String.valueOf(System.currentTimeMillis()));
        cv.put("description", name);
        cv.put("width", w);
        cv.put("height", h);
        cv.put("_display_name", file.getName());
        return cv;
    }

//    @TargetApi(29)
//    private static boolean getUri(Context context, File file, ContentValues cv, boolean isVideo, String directory) {
//        if (TextUtils.isEmpty(directory)) {
//            directory = Environment.DIRECTORY_DCIM + "/zkhczjz";
//        }
//        cv.put("relative_path", directory);
//        cv.put("is_pending", 1);
//        ContentResolver cr = context.getContentResolver();
//        Uri uri = cr.insert(isVideo ? android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI : MediaStore.Images.Media.EXTERNAL_CONTENT_URI, cv);
//        if (uri != null) {
//            BufferedInputStream bis = null;
//            OutputStream os = null;
//            try {
//                bis = new BufferedInputStream(new FileInputStream(file));
//                os = cr.openOutputStream(uri);
//                if (os != null) {
//                    byte[] b = new byte[4096];
//
//                    int r;
//                    while ((r = bis.read(b)) != -1) {
//                        os.write(b, 0, r);
//                    }
//
//                    os.flush();
//                    cv.put("is_pending", 0);
//                    cr.update(uri, cv, (String) null, (String[]) null);
//                }
//            } catch (IOException e) {
//                e.printStackTrace();
//            } finally {
//                if (os != null) {
//                    try {
//                        os.close();
//                    } catch (IOException e) {
//                        e.printStackTrace();
//                    }
//                }
//                if (bis != null) {
//                    try {
//                        bis.close();
//                    } catch (IOException e) {
//                        e.printStackTrace();
//                    }
//                }
//            }
//        }
//        return uri;
//    }


    /**
     * 删除文件，可以是文件或文件夹
     *
     * @param fileName 要删除的文件名
     * @return 删除成功返回true，否则返回false
     */
    public static boolean delete(String fileName) {
        File file = new File(fileName);
        if (!file.exists()) {
            System.out.println("删除文件失败:" + fileName + "不存在！");
            return false;
        } else {
            if (file.isFile())
                return deleteFile(fileName);
            else
                return deleteDirectory(fileName);
        }
    }

    /**
     * 删除单个文件
     *
     * @param fileName 要删除的文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteFile(String fileName) {
        File file = new File(fileName);
        // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                System.out.println("删除单个文件" + fileName + "成功！");
                return true;
            } else {
                System.out.println("删除单个文件" + fileName + "失败！");
                return false;
            }
        } else {
            System.out.println("删除单个文件失败：" + fileName + "不存在！");
            return false;
        }
    }

    /**
     * 删除目录及目录下的文件
     *
     * @param dir 要删除的目录的文件路径
     * @return 目录删除成功返回true，否则返回false
     */
    public static boolean deleteDirectory(String dir) {
        // 如果dir不以文件分隔符结尾，自动添加文件分隔符
        if (!dir.endsWith(File.separator))
            dir = dir + File.separator;
        File dirFile = new File(dir);
        // 如果dir对应的文件不存在，或者不是一个目录，则退出
        if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
            System.out.println("删除目录失败：" + dir + "不存在！");
            return false;
        }
        boolean flag = true;
        // 删除文件夹中的所有文件包括子目录
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            // 删除子文件
            if (files[i].isFile()) {
                flag = FileUtils.deleteFile(files[i].getAbsolutePath());
                if (!flag)
                    break;
            }
            // 删除子目录
            else if (files[i].isDirectory()) {
                flag = FileUtils.deleteDirectory(files[i]
                        .getAbsolutePath());
                if (!flag)
                    break;
            }
        }
        if (!flag) {
            System.out.println("删除目录失败！");
            return false;
        }
        // 删除当前目录
        if (dirFile.delete()) {
            System.out.println("删除目录" + dir + "成功！");
            return true;
        } else {
            return false;
        }
    }
}
